import io, os
import zipfile
import tempfile
import shutil


class Handler:
    _public_methods_ = ['close', 'list', 'load', 'write', 'read', 'extract', 'saveFile', 'saveBytes']
    compilation = None

    def __init__(self):
        self.__zFile = io.BytesIO()
        self.__tmpdir = tempfile.TemporaryDirectory()

    def close(self):
        self.__zFile.close()
        self.__tmpdir.cleanup()
        self.compilation = None

    def __compression(self):  #生成压缩数据
        with zipfile.ZipFile(self.__zFile, "w", zipfile.ZIP_DEFLATED, False) as process:
            for rt, dirs, files in os.walk(self.__tmpdir.name):
                for f in files:
                    path = os.path.join(rt,f)
                    process.write(path, path[len(self.__tmpdir.name):])

    def __isAbsolutePath(self, path):  #判断是否是完全绝对路径
        if os.path.splitdrive(os.path.abspath(path))[0]==os.path.splitdrive(path)[0]:
            return True
        else:
            return False

    def __getInternalPath(self, arcname):  #获得包内路径
        return os.path.abspath(os.path.join(self.__tmpdir.name, arcname))

    def load(self, path):
        result = False
        if self.__isAbsolutePath(path) and zipfile.is_zipfile(path):
            with zipfile.ZipFile(path, "r") as process:
                process.extractall(self.__tmpdir.name)
                result = True
        return result

    def getFileList(self):
        list = []
        for rt, dirs, files in os.walk(self.__tmpdir.name):
            for f in files:
                list.append(os.path.join(rt, f)[len(self.__tmpdir.name):])
        return self.compilation.VARIANT(self.compilation.constants.VT_VARIANT | self.compilation.constants.VT_ARRAY, list)

    def write(self, mode, arcname, contents):
        result = False
        if not isinstance(mode, str):
            mode = ''
        if not isinstance(arcname, str):
            arcname = ''
        storagePath = self.__getInternalPath(arcname)
        if storagePath.startswith(self.__tmpdir.name):
            storageDir = os.path.split(storagePath)[0]
            if not os.path.exists(storageDir):
                os.makedirs(storageDir)
            if mode.lower() == 'copy':
                if isinstance(contents, str):
                    if self.__isAbsolutePath(contents) and os.path.exists(contents):
                        shutil.copy(contents, storagePath)
                        result = True
            elif mode.lower() == 'create':
                if isinstance(contents, str):
                    contents = contents.encode("utf-8")
                if isinstance(contents, bytes):
                    with open(storagePath, mode='wb') as target:
                        target.write(contents)
                        result = True
        return result

    def read(self, arcname):
        data = None
        filePath = self.__getInternalPath(arcname)
        if filePath.startswith(self.__tmpdir.name) and os.path.exists(filePath):
            with open(filePath, 'rb') as target:
                data = target.read()
        return data

    def extract(self, arcname, path):
        result = False
        if self.__isAbsolutePath(path):
            target = self.__getInternalPath(arcname)
            if target.startswith(self.__tmpdir.name) and os.path.exists(target):
                shutil.copy(target, path)
                result = True
        return result

    def saveFile(self, path):
        result = False
        if self.__isAbsolutePath(path) and os.path.exists(os.path.split(path)[0]):
            self.__compression()
            self.__zFile.seek(0)
            with open(path, 'wb') as zfile:
                zfile.write(self.__zFile.read())
                zfile.close()
                result = True
        return result

    def saveBytes(self):
        self.__compression()
        self.__zFile.seek(0)
        return self.__zFile.read()